var GAME={}; //global namespace
var TEXTURE_PATH="resources/textures/";
time = new Date().getTime();

if ( !window.requestAnimationFrame ) {
	window.requestAnimationFrame = ( function() {

		return window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {
			window.setTimeout( callback, 1000 / 60 );
		};

	} )();
}

var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );

init();
animate();

function init() {

	GAME.container = document.getElementById( 'container' );

	GAME.scene = new THREE.Scene();
	
	var planetTexture = THREE.ImageUtils.loadTexture( TEXTURE_PATH+"earth_atmos_2048.jpg" ),
	cloudsTexture     = THREE.ImageUtils.loadTexture( TEXTURE_PATH+"earth_clouds_1024.png" ),
	normalTexture     = THREE.ImageUtils.loadTexture( TEXTURE_PATH+"earth_normal_2048.jpg" ),
	specularTexture   = THREE.ImageUtils.loadTexture( TEXTURE_PATH+"earth_specular_2048.jpg" ),
	moonTexture       = THREE.ImageUtils.loadTexture( TEXTURE_PATH+"moon_1024.jpg" );
	
	//Earth
	GAME.earth={
			radius:6371, //km
			rotationSpeed: 0.1,
			rotationSpeed: 0.1,
		};
	
	var shader = THREE.ShaderUtils.lib[ "normal" ],
	uniforms = THREE.UniformsUtils.clone( shader.uniforms );

	uniforms[ "tNormal" ].texture = normalTexture;
	uniforms[ "uNormalScale" ].value = 0.85;

	uniforms[ "tDiffuse" ].texture = planetTexture;
	uniforms[ "tSpecular" ].texture = specularTexture;

	uniforms[ "enableAO" ].value = false;
	uniforms[ "enableDiffuse" ].value = true;
	uniforms[ "enableSpecular" ].value = true;

	uniforms[ "uDiffuseColor" ].value.setHex( 0xffffff );
	uniforms[ "uSpecularColor" ].value.setHex( 0xbbbbbb );
	uniforms[ "uAmbientColor" ].value.setHex( 0xffffff );

	uniforms[ "uShininess" ].value = 5;

	GAME.earth.materialNormalMap = new THREE.MeshShaderMaterial({
		fragmentShader: shader.fragmentShader,
		vertexShader: shader.vertexShader,
		uniforms: uniforms,
		lights: true
	});
	
	GAME.earth.geometry = new THREE.SphereGeometry( GAME.earth.radius, 100, 100 );
	GAME.earth.geometry.computeTangents();

	GAME.earth.mesh = new THREE.Mesh( GAME.earth.geometry, GAME.earth.materialNormalMap );
	GAME.earth.mesh.rotation.y = 1.2;
	GAME.earth.mesh.rotation.z = 0.4;
	GAME.scene.addObject( GAME.earth.mesh );

	// clouds

	GAME.earth.clouds = { scale: 1.005 };
	GAME.earth.clouds.material = new THREE.MeshLambertMaterial( { color: 0xffffff, map: cloudsTexture, transparent:true } );
	GAME.earth.clouds.mesh = new THREE.Mesh( GAME.earth.geometry, GAME.earth.clouds.material );
	GAME.earth.clouds.mesh.scale.set( GAME.earth.clouds.scale, GAME.earth.clouds.scale, GAME.earth.clouds.scale );
	GAME.earth.clouds.mesh.rotation.z = 0.4;
	GAME.scene.addObject( GAME.earth.clouds.mesh );

	// moon

	GAME.moon = { scale: 0.273 };
	GAME.moon.material = new THREE.MeshPhongMaterial( { color: 0xffffff, map: moonTexture } );
	GAME.moon.mesh = new THREE.Mesh( GAME.earth.geometry, GAME.moon.material );
	GAME.moon.mesh.position.set( GAME.earth.radius * 5, 0, 0 );
	GAME.moon.mesh.scale.set( GAME.moon.scale,  GAME.moon.scale,  GAME.moon.scale );
	GAME.scene.addObject( GAME.moon.mesh );

	// stars

	var i, vector;
	GAME.stars={
		number : 1500,
		geometry: new THREE.Geometry(),
		materials: [
		     		new THREE.ParticleBasicMaterial( { color: 0x555555, size: 2, sizeAttenuation: false } ),
		     		new THREE.ParticleBasicMaterial( { color: 0x555555, size: 1, sizeAttenuation: false } ),
		     		new THREE.ParticleBasicMaterial( { color: 0x333333, size: 2, sizeAttenuation: false } ),
		     		new THREE.ParticleBasicMaterial( { color: 0x3a3a3a, size: 1, sizeAttenuation: false } ),
		     		new THREE.ParticleBasicMaterial( { color: 0x1a1a1a, size: 2, sizeAttenuation: false } ),
		     		new THREE.ParticleBasicMaterial( { color: 0x1a1a1a, size: 1, sizeAttenuation: false } )
		     	],
		systems:[]
	};
	for ( i = 0; i < GAME.stars.number; i++ ) {
		vector = new THREE.Vector3( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
		vector.multiplyScalar( GAME.earth.radius );
		GAME.stars.geometry.vertices.push( new THREE.Vertex( vector ) );
	}

	for ( i = 10; i < 30; i++ ) {
		stars = new THREE.ParticleSystem( GAME.stars.geometry, GAME.stars.materials[ i % 6 ] );
		
		stars.rotation.x = Math.random() * 6;
		stars.rotation.y = Math.random() * 6;
		stars.rotation.z = Math.random() * 6;
		
		var s = i * 5;
		stars.scale.set( s, s, s );

		stars.matrixAutoUpdate = false;
		stars.updateMatrix();
		GAME.stars.systems.push(stars);
		GAME.scene.addObject( stars );
	}
	
	//Lights
	GAME.lights={
		sun: new THREE.DirectionalLight( 0xFFFFFF ), //Sun light
		//shadow : new THREE.AmbientLight( 0x303030 ) //Pour pouvoir distinguer un peu la face obscure de la terre
	};
	
	GAME.lights.sun.position.set( -1, 0, 1 );
	GAME.lights.sun.position.normalize();
	GAME.scene.addLight( GAME.lights.sun );
	//GAME.scene.addLight( GAME.lights.shadow );
		
	GAME.renderer = new THREE.WebGLRenderer({ clearAlpha: 1, clearColor: 0x000000 });
	GAME.renderer.setSize( window.innerWidth, window.innerHeight );
	GAME.renderer.sortObjects = false;
	GAME.renderer.autoClear = true;

	GAME.camera = new THREE.TrackballCamera({

		fov: 25,
		aspect: window.innerWidth / window.innerHeight,
		near: 50,
		far: 1e7,

		rotateSpeed: 1.0,
		zoomSpeed: 1.2,

		noZoom: false,
		noPan: true,

		staticMoving: false,
		dynamicDampingFactor: 0.3,

		minDistance: GAME.earth.radius * 1.5,
		maxDistance: GAME.earth.radius * 10,

		domElement: GAME.renderer.domElement,

	});
	
	GAME.camera.position.z = GAME.earth.radius * 5;
	
	GAME.container.appendChild( GAME.renderer.domElement );

	//Event Listeners
	document.addEventListener( 'mousemove', onDocumentMouseMove, false );
	$(document).mousewheel(onDocumentMouseWheel);

	log('Start');

}

function onDocumentMouseMove( event ) {
}

function onDocumentMouseWheel( event, delta ) {
	if(delta>0 && GAME.camera.distance > 220) GAME.camera.distance -= 20;
	else if(delta<0 && GAME.camera.distance < 2000) GAME.camera.distance += 20;
}


function animate() {
	requestAnimationFrame( animate );
	render();
	stats.update();
}

function render() {
	var t = new Date().getTime(), dt = ( t - time ) / 1000;
	time = t;

	GAME.earth.mesh.rotation.y += GAME.earth.rotationSpeed * dt;
	GAME.earth.clouds.mesh.rotation.y += 1.25 * GAME.earth.rotationSpeed * dt;

	var angle = dt * GAME.earth.rotationSpeed;

	GAME.moon.mesh.position = new THREE.Vector3(
		Math.cos( angle ) * GAME.moon.mesh.position.x - Math.sin( angle ) * GAME.moon.mesh.position.z,
		0,
		Math.sin( angle ) * GAME.moon.mesh.position.x + Math.cos( angle ) * GAME.moon.mesh.position.z
	);
	GAME.moon.mesh.rotation.y -= angle;
	GAME.renderer.render( GAME.scene, GAME.camera );
}